package com.kly.sc.api.integration.userplatform.util;


import com.alibaba.fastjson.JSONObject;
import com.kly.sc.api.infras.exception.ApplicationException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import okhttp3.logging.HttpLoggingInterceptor;
import okhttp3.logging.HttpLoggingInterceptor.Level;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Component
public class ApiUtils {
    private static OkHttpClient client;
    private static Map<String, String> headers = new HashMap();
    private static String version = null;

//    @Value("${user.api.url}")
    private String API_URL;

    ApiUtils() {
    }

    public static void createHttpClientInstance(boolean enableLogging) throws ApplicationException {
        if (client == null) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            if (enableLogging) {
                loggingInterceptor.setLevel(Level.BASIC);
            } else {
                loggingInterceptor.setLevel(Level.NONE);
            }

            try {
                client = (new OkHttpClient.Builder()).readTimeout(60L, TimeUnit.SECONDS).writeTimeout(60L, TimeUnit.SECONDS)
                        .addInterceptor(loggingInterceptor).sslSocketFactory(new CustomTLSSocketFactory(), createDefaultTrustManager()).build();
            } catch (Exception e) {
                throw new ApplicationException("CreateHttpClientFailed", e);
            }
        }

        Properties properties = new Properties();
        if (StringUtils.isBlank(version)) {
            version = "1.0";
        }
        /*try {
            properties.load(ApiUtils.class.getResourceAsStream("/project.properties"));
            version = (String) properties.get("version");
        } catch (IOException e) {
            throw new ApplicationException(e.getMessage());
        }*/
    }

    static Response postRequest(String url, String path, JSONObject requestObject, String auth) throws ApplicationException {
        okhttp3.HttpUrl.Builder builder = getBuilder(url, path);
        String requestContent = requestObject == null ? "" : requestObject.toString();
        RequestBody requestBody = RequestBody.create(Constants.MEDIA_TYPE_JSON, requestContent);
        Request request = createRequest(ApiUtils.Method.POST.name(), builder.build().toString(), requestBody, auth);
        return processRequest(request);
    }

    static Response postRequestSSL(String host, String path, JSONObject requestObject, String auth) throws ApplicationException {
        okhttp3.HttpUrl.Builder builder = getBuilderSSL(host, path);
        String requestContent = requestObject == null ? "" : requestObject.toString();
        RequestBody requestBody = RequestBody.create(Constants.MEDIA_TYPE_JSON, requestContent);
        Request request = createRequest(ApiUtils.Method.POST.name(), builder.build().toString(), requestBody, auth);
        return processRequest(request);
    }

    static Response putRequest(String host, String path, JSONObject requestObject, String auth) throws ApplicationException {
        okhttp3.HttpUrl.Builder builder = getBuilder(host, path);
        String requestContent = requestObject == null ? "" : requestObject.toString();
        RequestBody requestBody = RequestBody.create(Constants.MEDIA_TYPE_JSON, requestContent);
        Request request = createRequest(ApiUtils.Method.PUT.name(), builder.build().toString(), requestBody, auth);
        return processRequest(request);
    }

    static Response patchRequest(String host, String path, JSONObject requestObject, String auth) throws ApplicationException {
        okhttp3.HttpUrl.Builder builder = getBuilder(host, path);
        String requestContent = requestObject == null ? "" : requestObject.toString();
        RequestBody requestBody = RequestBody.create(Constants.MEDIA_TYPE_JSON, requestContent);
        Request request = createRequest(ApiUtils.Method.PATCH.name(), builder.build().toString(), requestBody, auth);
        return processRequest(request);
    }

    static Response getRequest(String host, String path, JSONObject requestObject, String auth) throws ApplicationException {
        okhttp3.HttpUrl.Builder builder = getBuilder(host, path);
        addQueryParams(builder, requestObject);
        Request request = createRequest(ApiUtils.Method.GET.name(), builder.build().toString(), (RequestBody) null, auth);
        return processRequest(request);
    }

    static Response deleteRequest(String host, String path, JSONObject requestObject, String auth) throws ApplicationException {
        okhttp3.HttpUrl.Builder builder = getBuilder(host, path);
        addQueryParams(builder, requestObject);
        Request request = createRequest(ApiUtils.Method.DELETE.name(), builder.build().toString(), (RequestBody) null, auth);
        return processRequest(request);
    }

    private static okhttp3.HttpUrl.Builder getBuilder(String host, String path) {
//        return (new okhttp3.HttpUrl.Builder()).scheme("http").host(API_URL).port(Constants.PORT).addPathSegments(path);
        return (new okhttp3.HttpUrl.Builder()).scheme("http").host(host).port(Constants.PORT).addPathSegments(path);
    }

    private static okhttp3.HttpUrl.Builder getBuilderSSL(String host, String path) {
        return (new okhttp3.HttpUrl.Builder()).scheme("https").host(host).port(Constants.PORT_443).addPathSegment("v1").addPathSegments(path);
    }

    private static Request createRequest(String method, String url, RequestBody requestBody, String auth) {
        okhttp3.Request.Builder builder = (new okhttp3.Request.Builder()).url(url).addHeader("Authorization", auth);
        builder.addHeader("User-Agent", "userApi/v1 JAVASDK/" + version + " Java/" + System.getProperty("java.version"));
        Iterator var5 = headers.entrySet().iterator();

        while (var5.hasNext()) {
            Map.Entry<String, String> header = (Map.Entry) var5.next();
            builder.addHeader((String) header.getKey(), (String) header.getValue());
        }

        return builder.method(method, requestBody).build();
    }

    private static void addQueryParams(okhttp3.HttpUrl.Builder builder, JSONObject request) {
        if (request != null) {
            final Set<String> keySet = request.keySet();
            for (String key : keySet) {
                builder.addQueryParameter(key, request.get(key).toString());
            }

        }
    }

    private static Response processRequest(Request request) throws ApplicationException {
        try {
            return client.newCall(request).execute();
        } catch (IOException var2) {
            throw new ApplicationException(var2.getMessage());
        }
    }

    public static void addHeaders(Map<String, String> header) {
        headers.putAll(header);
    }

    private static X509TrustManager createDefaultTrustManager() throws NoSuchAlgorithmException, KeyStoreException {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init((KeyStore) null);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length == 1 && trustManagers[0] instanceof X509TrustManager) {
            X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
            return trustManager;
        } else {
            throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
        }
    }

    private static enum Method {
        GET,
        POST,
        PUT,
        PATCH,
        DELETE;

        private Method() {
        }
    }
}